#pragma once
#include "Epoller.hpp"
#include "Connection.hpp"
#include "Log.hpp"

#include <sys/epoll.h>
#include <unordered_map>
const int maxevents = 64;

#define EPOLL_BLOCK -1
class TcpServer
{
public:
    TcpServer(int timeout = EPOLL_BLOCK) : _timeout(timeout)
    {
        _epoller.InitEpoller(); // 不然会报9号错误
    }
    bool IsConnectionExit(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        return iter != _connections.end();

        // return _connections.count(sockfd);
    }
    void AddConnetion(Connection *conn)
    {
        // if(!conn || IsConnectionExit(conn->GetSockfd())) return;
        if (!conn || IsConnectionExit(conn->GetSockfd()))
        {
            lg.LogMessage(Warning, "Connection already exists or invalid connection!\n");
            return;
        }
        _connections.insert(std::make_pair(conn->GetSockfd(), conn));
        lg.LogMessage(Info, "add connection success... sockfd: %d\n", conn->GetSockfd());

        _epoller.AddEvent(conn->GetSockfd(), conn->GetEvents());
    }
    void LoopOnce()
    {
        int n = _epoller.Wait(_revs, maxevents, _timeout);
        std::cout << n << std::endl;
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;

            if (events & EPOLLERR || events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);

            if (IsConnectionExit(sockfd)) // sockfd是否在connections里，下面有解引用
            {
                if (events & EPOLLIN && _connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
                if (events & EPOLLOUT && _connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }
    void Dispatcher()
    {
        while (true)
        {
            std::cout << "xxx" << std::endl;
            LoopOnce();
        }
    }

private:
    Epoller _epoller;
    struct epoll_event _revs[maxevents];
    int _timeout;
    std::unordered_map<int, Connection *> _connections;
};